const chalk = require('chalk')
const padStart = require('string.prototype.padstart')
const path = require('path')
const merge = require('webpack-merge')

const format = (label, msg) => {
  return msg.split('\n').map((line, i) => {
    return i === 0
      ? `${label} ${line}`
      : padStart(line, chalk.reset(label).length)
  }).join('\n')
}

const chalkTag = msg => chalk.bgBlackBright.white.dim(` ${msg} `)

/**
 * 解析传入参数.
 * @function
 * @param {string} rawArgv
 */
exports.parseArgs = function (rawArgv, options = {}) {
  return require('minimist')(rawArgv, options)
}

exports.error = (msg, tag = null) => {
  console.error(format(chalk.bgRed(' ERROR ') + (tag ? chalkTag(tag) : ''), chalk.red(msg)))
  if (msg instanceof Error) {
    console.error(msg.stack)
  }
}

exports.log = (msg = '', tag = null) => {
  tag ? console.log(format(chalkTag(tag), msg)) : console.log(msg)
}

exports.info = (msg, tag = null) => {
  console.log(format(chalk.bgBlue.black(' INFO ') + (tag ? chalkTag(tag) : ''), msg))
}

exports.done = (msg, tag = null) => {
  console.log(format(chalk.bgGreen.black(' DONE ') + (tag ? chalkTag(tag) : ''), msg))
}

exports.warn = (msg, tag = null) => {
  console.warn(format(chalk.bgYellow.black(' WARN ') + (tag ? chalkTag(tag) : ''), chalk.yellow(msg)))
}

// -----------------------------------
// webpack helper  ||
// -----------------------------------
exports.DEFAULT_TARGETS = {
  renderer: 'renderer',
  main: 'main'
}

exports.DEFAULT_TARGET_ENTRIES = {
  [ exports.DEFAULT_TARGETS.main ]: './src/main/index.ts',
  [ exports.DEFAULT_TARGETS.renderer ]: './src/renderer/index.ts'
}

/**
 * 根据传入的 target 创建一个基于 target 的 config.
 * @function
 * @param {'renderer'|'main'} target
 * @param {string} env
 * @param {Array} customConfigs
 * @returns webpack config
 */
exports.makeConfig = function (target, env, ...customConfigs) {
  const baseConfig = require('./config/webpack.base.config')
  const envConfig = require(`./config/webpack.base.${env}.config`)

  const entry = exports.DEFAULT_TARGET_ENTRIES[ target ]

  const plugins = []
  if (target === exports.DEFAULT_TARGETS.renderer) {
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    plugins.push(new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve(__dirname, '../src/index.ejs'),
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true,
        removeComments: true
      },
      nodeModules: process.env.NODE_ENV !== 'production'
        ? path.resolve(__dirname, '../node_modules')
        : false
    }))
  }

  let externals = []
  if (target === exports.DEFAULT_TARGETS.main) {
    const { dependencies } = require('../package.json')
    externals = [
      ...Object.keys(dependencies || {})
    ]
  } else if (target === exports.DEFAULT_TARGETS.renderer) {
    // renderer here
  }
  return merge.smart(baseConfig, envConfig, {
    entry: { [ target ]: entry },
    output: {
      filename: '[name].js',
      path: path.resolve(__dirname, '../dist/')
    },
    externals,
    plugins: plugins,
    target: target === 'renderer' ? 'electron-renderer' : 'electron-main'
  }, ...customConfigs)
}

exports.compileCallback = function (resolve, reject) {
  return (err, stats) => {
    if (err) reject(err.stack || err)
    else if (stats.hasErrors()) {
      let err = ''

      stats.toString({
        chunks: false,
        colors: true
      })
        .split(/\r?\n/)
        .forEach(line => {
          err += `    ${line}\n`
        })

      reject(err)
    } else {
      resolve(stats.toString({
        chunks: false,
        colors: true
      }))
    }
  }
}
